using AutoMapper;
using MediatR;
using ProduceBasicData.Api.Application.Command.WarehouseManage;
using ProduceBasicData.Domain.WarehouseManage;
using ProduceBasicData.Domain.WarehouseManage.WarehouseEnum;
using ProduceBasicData.ErrorCode;
using ProduceBasicData.Infrastructure.Interface;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ProduceBasicData.Api.Application.Handler.WarehouseManage
{
    /// <summary>
    /// 入库操作请求处理器
    /// </summary>
    public class InWarehouseHandler : IRequestHandler<InWarehouseCommand, ApiResult<int>>
    {
        private readonly IBaseRespository<StockInOrder> _stockInOrderRepository;
        private readonly IBaseRespository<StockInOrderItem> _stockInOrderItemRepository;
        private readonly IBaseRespository<Inventory> _inventoryRepository;
        private readonly IMapper _mapper;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="stockInOrderRepository">入库单仓储</param>
        /// <param name="stockInOrderItemRepository">入库单明细仓储</param>
        /// <param name="inventoryRepository">库存仓储</param>
        /// <param name="mapper">对象映射器</param>
        public InWarehouseHandler(
            IBaseRespository<StockInOrder> stockInOrderRepository,
            IBaseRespository<StockInOrderItem> stockInOrderItemRepository,
            IBaseRespository<Inventory> inventoryRepository,
            IMapper mapper)
        {
            _stockInOrderRepository = stockInOrderRepository;
            _stockInOrderItemRepository = stockInOrderItemRepository;
            _inventoryRepository = inventoryRepository;
            _mapper = mapper;
        }

        /// <summary>
        /// 处理入库操作请求
        /// </summary>
        /// <param name="request">入库命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>操作结果</returns>
        public async Task<ApiResult<int>> Handle(InWarehouseCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<int>();

            try
            {
                // 1. 获取入库单信息
                var stockInOrder = await _stockInOrderRepository.GetModelAsync(request.Id);
                if (stockInOrder == null || stockInOrder.Isdel)
                {
                    result.Code = ApiEnum.Failed;
                    result.Msg = "未找到指定的入库单";
                    return result;
                }

                // 2. 检查入库单状态
                if (stockInOrder.Status != StockInStatus.Pending)
                {
                    result.Code = ApiEnum.Failed;
                    result.Msg = "只有待入库的入库单才能执行入库操作";
                    return result;
                }

                // 3. 开启事务
                using (var transaction = await _stockInOrderRepository.DB.Database.BeginTransactionAsync(cancellationToken))
                {
                    try
                    {
                        // 4. 获取入库单明细（使用带条件的查询）
                        var items = await _stockInOrderItemRepository.GetAllAsync(
                            i => i.StockInOrderId == request.Id && !i.Isdel
                        );

                        if (!items.Any())
                        {
                            result.Code = ApiEnum.Failed;
                            result.Msg = "入库单没有明细，无法执行入库操作";
                            return result;
                        }

                        // 5. 处理库存（使用新增的NoSave方法）
                        foreach (var item in items)
                        {
                            var inventory = await _inventoryRepository.GetFirstOrDefaultAsync(
                                i => i.MaterialId == item.MaterialId &&
                                     i.WarehouseId == stockInOrder.WarehouseId &&
                                     i.BatchNumber == item.BatchNumber &&
                                     !i.Isdel
                            );

                            if (inventory != null)
                            {
                                // 仅更新状态，不保存
                                inventory.Quantity += item.ActualQuantity;
                                inventory.LastInTime = DateTime.Now;
                                _inventoryRepository.UpdateNoSave(inventory);
                            }
                            else
                            {
                                // 仅添加状态，不保存
                                var newInventory = new Inventory
                                {
                                    MaterialId = item.MaterialId,
                                    MaterialCode = item.MaterialCode,
                                    MaterialName = item.MaterialName,
                                    Specification = item.Specification,
                                    WarehouseId = stockInOrder.WarehouseId,
                                    LocationId = item.TargetLocationId ?? 0,
                                    BatchNumber = item.BatchNumber,
                                    ProductionDate = item.ProductionDate,
                                    ExpirationDate = item.ExpirationDate,
                                    Quantity = item.ActualQuantity,
                                    Unit = item.Unit,
                                    InventoryStatus = "正常",
                                    LastInTime = DateTime.Now
                                };
                                await _inventoryRepository.AddNoSaveAsync(newInventory);
                            }
                        }

                        // 6. 更新入库单状态（使用新增的NoSave方法）
                        stockInOrder.Status = StockInStatus.Completed;
                        stockInOrder.ActualInDate = DateTime.Now;
                        stockInOrder.UpdateName = request.UpdateName;
                        stockInOrder.UpdateTime = DateTime.Now;
                        _stockInOrderRepository.UpdateNoSave(stockInOrder);

                        // 7. 事务内统一保存所有变更（关键：仅一次SaveChanges）
                        await _stockInOrderRepository.SaveChangesAsync();

                        // 8. 提交事务
                        await transaction.CommitAsync(cancellationToken);

                        result.Code = ApiEnum.Success;
                        result.Msg = "入库操作成功";
                        result.Data = stockInOrder.Id;
                    }
                    catch (Exception ex)
                    {
                        await transaction.RollbackAsync(cancellationToken);
                        result.Code = ApiEnum.Failed;
                        result.Msg = "入库操作失败：" + ex.Message;
                    }
                }
            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.Failed;
                result.Msg = "处理入库操作时发生异常：" + ex.Message;
            }

            return result;
        }
    }
}